package com.yixing.tech.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yixing.tech.common.base.*;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.enums.UserType;
import com.yixing.tech.common.service.CommonService;
import com.yixing.tech.common.vo.s3.LogInfo;
import com.yixing.tech.common.vo.s3.TenantVO;
import com.yixing.tech.common.vo.s3.UserVO;
import com.yixing.tech.common.vo.s3.WxPublicInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yixing tech
 * at 2022/10/15
 * describe：
 */
@Slf4j
@Component
public class WxApiUtil {


    private static WxApiUtil self;

    @Resource
    private MongoTemplate mongoTemplate;

    private static String wxTokenHttp = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={1}&secret={2}";
    public static String wxSendMsgHttp = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={1}";
    private static String wxGetPublicUserIdsHttp = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={1}&next_openid={2}";
    private static String wxGetPublicUsersHttp = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token={1}";
    private static String wxGetUserPhoneHttp = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=={1}";


    @PostConstruct
    private void init() {
        self = this;
    }

    /**
     * 获取微信token
     *
     * @param appId
     * @param secret
     * @return
     * @throws BusinessException
     */
    public static String getWxToken(String appId, String secret) throws BusinessException {
        if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(secret))
            throw new BusinessException(ErrCode.PARAMETER_ERROR);
        RestTemplate restTemplate = new RestTemplate();
//        List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
//        list.add(new JsonbHttpMessageConverter());
//        restTemplate.setMessageConverters(list);
        String wpStr = restTemplate.getForObject(wxTokenHttp, String.class, appId, secret);
        WxTokenResponse wp = JSONObject.parseObject(wpStr, WxTokenResponse.class);
        if (wp.isOk()) {
            return wp.getAccess_token();
        } else {
            throw new BusinessException(ErrCode.UNAUTHORIZED);
        }
    }

    /**
     * 获取公众号用户列表
     *
     * @return
     * @throws BusinessException
     */
    public static List<WxPublicInfoVO> getPublicUsers(String token) throws BusinessException {
        List<WxPublicInfoVO> datas = new ArrayList<>();
        List<String> openIds = new ArrayList<>();
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
        list.add(new JsonbHttpMessageConverter());
        restTemplate.setMessageConverters(list);
        //获取openId列表
        getPublicUserIds(restTemplate, openIds, token, "");
        //获取用户基本信息

        int size = openIds.size() / 100;
        int count = openIds.size() % 100;
        for (int i = 0; i < size; i++) {
            List<String> ids = openIds.subList(i * 100, (i + 1) * 100);
            getPublicUsers(restTemplate, datas, ids, token);
        }
        List<String> ids = openIds.subList(openIds.size() - count, openIds.size());
        getPublicUsers(restTemplate, datas, ids, token);
        return datas;
    }

    private static void getPublicUserIds(RestTemplate restTemplate, List<String> list, String token, String nextOpenId) throws BusinessException {
        WxPublicUserIdsResponse wp = restTemplate.getForObject(wxGetPublicUserIdsHttp, WxPublicUserIdsResponse.class, token, nextOpenId);
        if (wp.isOk()) {
            List<String> openId = wp.getData().getOpenid();
            list.addAll(openId);
            long total = wp.getTotal();
            if (list.size() < total) {
                getPublicUserIds(restTemplate, list, token, wp.getNext_openid());
            }
        }
    }

    private static void getPublicUsers(RestTemplate restTemplate, List<WxPublicInfoVO> list, List<String> ids, String token) throws BusinessException {
        if (CommonUtil.listIsBlank(ids)) return;
        Map<String, Object> map = new HashMap<>(1);
        List<Map> openIds = ids.stream().map(m -> {
            Map map1 = new HashMap(1);
            map1.put("openid", m);
            return map1;
        }).collect(Collectors.toList());
        map.put("user_list", openIds);
        WxPublicUsersResponse wp = restTemplate.postForObject(wxGetPublicUsersHttp, map, WxPublicUsersResponse.class, token);
        if (wp.isOk()) {
            list.addAll(wp.getUser_info_list());
        }
    }


    public static void sendMsg(String tenantId, List<String> userIds, String titleStr, String descStr, String firstStr, String proposer) throws BusinessException {
        log.info("------sendWxMsg------:" + Arrays.toString(userIds.toArray()));
        TenantVO tenant = self.mongoTemplate.findById(new ObjectId(tenantId), TenantVO.class, "tenant");
        if (tenant == null || StringUtils.isEmpty(tenant.getMsgTemplateId())) return;
        String token = WxApiUtil.getWxToken(tenant.getAppletAppId(), tenant.getAppletSecret());
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
        list.add(new JsonbHttpMessageConverter());
        restTemplate.setMessageConverters(list);

        Map<String, Object> content = new HashMap<>(4);
        Map<String, Object> userName = new HashMap<>(2);
        Map<String, String> time = new HashMap<>(2);
        Map<String, String> title = new HashMap<>(2);
        Map<String, String> desc = new HashMap<>(2);
        Map<String, String> first = new HashMap<>(2);
        title.put("color", "#173177");
        time.put("color", "#173177");
        desc.put("color", "#173177");
        first.put("color", "#173177");
        userName.put("color", "#173177");

        title.put("value", titleStr);
        time.put("value", DateUtil.getDateStr(new SimpleDateFormat(
                "yyyy-MM-dd HH:mm:ss")));
        desc.put("value", descStr);
        first.put("value", firstStr);
        userName.put("value", proposer);
        content.put("first", first);
        content.put("keyword1", userName);
        content.put("keyword2", title);
        content.put("keyword3", time);
        content.put("remark", desc);

        Map<String, Object> map = new HashMap<>(6);
        Map<String, Object> contentMap = new HashMap<>();
        contentMap.put("data", content);
        Map<String, String> miniprogram = new HashMap<>(2);
        miniprogram.put("pagepath", "pages/flow/list/index");
        contentMap.put("miniprogram", miniprogram);
        contentMap.put("url", "http://weixin.qq.com/download");

        miniprogram.put("appid", tenant.getAppletAppId());
        contentMap.put("template_id", tenant.getMsgTemplateId());
        contentMap.put("appid", tenant.getPublicAppId());
        map.put("mp_template_msg", contentMap);

        for (String userId : userIds) {
            UserVO user = self.mongoTemplate.findById(new ObjectId(userId), UserVO.class, "user");
            if (user == null || UserType.微信用户 != user.getType()) continue;
            String unionId = user.getUnionId();
            Document doc = self.mongoTemplate.findOne(Query.query(Criteria.where("unionid").is(unionId)), Document.class, "entity_634ffee1f296ec114c2e0c2f");
            if (doc == null || doc.getLong("subscribe") != 1) continue;
            map.put("touser", doc.getString("openid"));
            WxBaseResponse response = restTemplate.postForObject(WxApiUtil.wxSendMsgHttp, map, WxBaseResponse.class, token);
            if (!response.isOk()) {
                log.error("----sendWxMsg----:" + response.getErrmsg());
            } else {
                LogInfo logInfo = new LogInfo();
                logInfo.setTenantId(tenantId);
                logInfo.setPath("/sendWxMsg");
                logInfo.setMethod("post");
                logInfo.setName("消息推送");
                logInfo.setContent(JSON.toJSONString(map));
                self.mongoTemplate.save(logInfo);
            }

        }
    }


    /**
     * 获取微信手机号
     *
     * @param code
     * @param token
     * @return
     * @throws BusinessException
     */
    public static String getUserPhone(String code, String token) throws BusinessException {
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
        list.add(new JsonbHttpMessageConverter());
        restTemplate.setMessageConverters(list);
        Map<String, Object> map = new HashMap<>(1);
        map.put("code", code);
        WxUserPhoneResponse wp = restTemplate.postForObject(wxGetUserPhoneHttp, map, WxUserPhoneResponse.class, token);
        if (wp.isOk()) {
            return wp.getPhone_info().getPurePhoneNumber();
        }
        throw new BusinessException(ErrCode.PARAMETER_ERROR, wp.getErrmsg());
    }


}
